package com.mntp.proxy.jdkProxyDemo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 模拟rpc远程调用的原理，底层是代理实现的，可以在代理里面编写网络调用的逻辑，然后返回远程数据
 */
public class JdkProxyTest {


    public static void main(String[] args) {
        //查看生成的代理类的具体方法
        //该设置会把生成的class保存到com/sun/proxy文件下  jdk1.8能看到代理类， 高版本jdk隐藏了代理类
        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        BookService bookService=(BookService)Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class[]{BookService.class},
                new Handler());
        Book book = bookService.findBook(1);
        System.out.println(book);



    }


    /**
     * 这个类作为InvocationHandler的实现，主要用于处理代理对象的调用
     * 它拦截通过代理对象调用的方法，并执行自定义的操作
     */
    static class Handler implements InvocationHandler {

        /**
         * 处理代理对象的方法调用
         * 这个方法拦截被代理对象的所有方法调用，并执行自定义的逻辑
         *
         * @param proxy 代理对象，调用这个方法的代理实例
         * @param method 被调用的方法对象，表示正在调用的方法
         * @param args 方法参数，表示调用方法时传递的参数
         * @return 返回调用方法的结果，这里是一个Book对象
         * @throws Throwable 如果调用的方法抛出异常，此方法将抛出相同的异常
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 获取被调用方法的名称
            String name = method.getName();
            // 打印方法名，用于调试和日志记录
            System.out.println(name);
            // 模拟远程调用的过程
            System.out.println("发起了网络调用");
            // 创建并初始化一个Book对象，作为方法调用的结果返回
            Book book = new Book();
            book.setId(1);
            book.setName("水浒传");
            return book;
        }
    }
}
